#include <ros/ros.h>
#include <std_msgs/Bool.h>
#include <std_msgs/Int32.h>
#include <std_msgs/String.h>  // 添加String消息类型
#include "opencv2/opencv.hpp"
#include <zbar.h> // zbar库 sudo apt-get install libzbar0 libzbar-dev
#include <iostream>
#include <string>
#include <vector>

using namespace std;
bool scan_flag = false;

void scanCallback(const std_msgs::Bool::ConstPtr& msg) {
    scan_flag = msg->data;
}

int main(int argc, char** argv) {
    ros::init(argc, argv, "qr_code_scanner");
    ros::NodeHandle nh;

    ros::Subscriber scan_sub = nh.subscribe("scan_flag", 10, scanCallback);
    ros::Publisher result_pub = nh.advertise<std_msgs::Int32>("scan_result", 10);
    ros::Publisher text_result_pub = nh.advertise<std_msgs::String>("scan_text_result", 10); // 新增字符串结果发布器

    cv::VideoCapture cap(2, cv::CAP_V4L2);
    // cv::VideoCapture cap("/home/firefly/Videos/WIN_20250507_20_48_57_Pro.mp4");

    if (!cap.isOpened()) {
        ROS_ERROR("can't open cem");
        return -1;
    }

    // 设置摄像头的输入格式为MJPG
    cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));

    zbar::ImageScanner scanner;
    scanner.set_config(zbar::ZBAR_NONE, zbar::ZBAR_CFG_ENABLE, 1);

    ros::Rate loop_rate(30); 
    while (ros::ok()) {
        cv::Mat frame;
        cap >> frame;
        if (frame.empty()) {
            ROS_ERROR("can't get frame");
            break;
        }

        scan_flag = true;
        std_msgs::Int32 result_msg;
        std_msgs::String text_result_msg;
        result_msg.data = -1; // 默认值为-1表示未找到有效数字
        text_result_msg.data = ""; // 默认为空字符串

        if (scan_flag) {
            cv::Mat gray;
            cv::cvtColor(frame, gray, cv::COLOR_BGR2GRAY);

            zbar::Image image(frame.cols, frame.rows, "Y800", gray.data, frame.cols * frame.rows);
            int n = scanner.scan(image);

            bool found = false;
            cout << "test: " << 1 << endl;
            
            for (auto symbol = image.symbol_begin(); symbol != image.symbol_end(); ++symbol) {
                cout << "test: " << 2 << endl;
                
                // 获取扫描内容（字符串格式）
                std::string data_str = symbol->get_data();
                
                // 发布字符串消息
                text_result_msg.data = data_str;
                
                // 打印扫描内容（不论内容是什么）
                std::cout << "解码数据: " << data_str << std::endl;
                std::cout << "条码类型: " << symbol->get_type_name() << std::endl;
                
                // 尝试转换为整数（用于兼容旧代码）
                try {
                    int data = std::stoi(data_str);
                    if (data >= 1 && data <= 24) {
                        result_msg.data = data;
                        found = true;         
                    }
                } catch (std::exception& e) {
                    // 如果无法转换为整数，保持result_msg.data为-1
                    // ROS_INFO("扫描内容非1-24范围内的数字: %s", data_str.c_str());
                }

                // 在图像上绘制矩形框
                std::vector<cv::Point> points;
                for (int i = 0; i < symbol->get_location_size(); i++) {
                    points.push_back(cv::Point(symbol->get_location_x(i), symbol->get_location_y(i)));
                }
                cv::polylines(frame, points, true, cv::Scalar(0, 255, 0), 2);
                
                // 在二维码上方绘制文本
                cv::Point textPos(points[0].x, points[0].y - 10);
                cv::putText(frame, data_str, textPos, cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 2);
            }
        }

        // 发布整数结果
        result_pub.publish(result_msg);
        
        // 发布字符串结果（如果有内容）
        if (!text_result_msg.data.empty()) {
            text_result_pub.publish(text_result_msg);
        }

        cout << "Scan Result: " << result_msg.data << endl;
        if (!text_result_msg.data.empty()) {
            cout << "Text Result: " << text_result_msg.data << endl;
        }
        
        cv::imshow("Camera Feed", frame);
        if (cv::waitKey(1) == 27) 
        { 
            break;
        }

        ros::spinOnce();
        loop_rate.sleep();
    }

    return 0;
}